
import std.random;
import std.math;

import std.stdio:writefln;

class Neuron{
	this(int size){
		w.length = size;
		for(int i = 0; i < size; i++)
			w[i] = (rand() % 5) - 10;
		sigma = rand() % 2;
		if(sigma == 0)
			sigma = -1;
	}

	float w[];
	int sigma;
}

class Vertex{

	this(int _x, int _y){
		x = _x;
		y = _y;
	}

	int x;
	int y;
}

float dist(int x0, int y0, int x1, int y1){
	return sqrt(cast(float)( (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1) ));
}


class Graph{
	const int iterations = 10000000;
	const float lambda0 = 2.0f;
	const float lambda1 = 1.5f;

	this(){
	}

	void addVertex(int x, int y){
		vertices ~= new Vertex(x, y);
	}

	void allocAM(){
		writefln("vertices.length ==", vertices.length);
		adjacencyMatrix.length = vertices.length;
		for(int i = 0; i < vertices.length; i++)
			adjacencyMatrix[i].length = vertices.length;

		for(int i = 0; i < vertices.length; i++)
			for(int j = 0; j < vertices.length; j++)
				adjacencyMatrix[i][j] = adjacencyMatrix[j][i] = 0.0f;
	}

	void debugInfo(){
		writefln(vertices);
		writefln(adjacencyMatrix);
	}

	int getNearest(int x, int y, float maxDist){
		int ret = -1;
		float minDist = float.max;
		foreach(int i, vert;vertices){
			float dst = dist(x,y ,vert.x,vert.y);
			if(dst <= 10 && dst < minDist){
				minDist = dst;
				ret = i;
			}
		}
		return ret;
	}


	void addEdge(int a, int b){
		if(a != b && a > -1 && b > -1)
		adjacencyMatrix[a][b] = adjacencyMatrix[b][a] = dist(vertices[a].x, vertices[a].y, vertices[b].x, vertices[b].y)/100.f;
	}

	float sigmaI(int i){
		float ret = 0.0f;
		for(int j = 0; j < neurons.length; j++)
			if(i != j)
				ret += neurons[i].w[j]*neurons[j].sigma;
		return ret;
	}

	int sign(float a){
		if(a > 0.0f)
			return 1;
		if(a <= 0.0f)
			return -1;
	}


	void train(){
		writefln("Training");
		neurons.length = vertices.length;
		for(int i = 0; i < vertices.length; i++)
				neurons[i] = new Neuron(vertices.length);

		int size = vertices.length;
		for(int i = 0; i < iterations; i++){
			int x = rand() % size;
			int y = rand() % size;

			neurons[x].sigma = sign(sigmaI(x));
			neurons[x].w[y] = -2.0f * (lambda0 - lambda1*adjacencyMatrix[x][y]);

		}

		writefln("Done");

	}

	Vertex[] vertices;
	float[][] adjacencyMatrix = null;
	Neuron[] neurons = null;
}
